package io.vertx.examples.spring.verticle;

import java.util.Date;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;
import io.vertx.examples.spring.common.Result;
import io.vertx.examples.spring.common.ResultGenerator;
import io.vertx.examples.spring.entity.Product;
import io.vertx.examples.spring.messagecodec.ProductCodec;
import io.vertx.examples.spring.service.ProductService;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

/**
 * Simple web server verticle to expose the results of the Spring service bean
 * call (routed via a verticle - see SpringDemoVerticle)
 */
public class ServerVerticle extends AbstractVerticle {


	Logger logger = LoggerFactory.getLogger(ServerVerticle.class);

	private final ProductService service;

	public ServerVerticle(final ApplicationContext context) {
		service = (ProductService) context.getBean("productService");
	}

	@Override
	public void start() throws Exception {
		super.start();
		
		EventBus eventBus = getVertx().eventBus();

		Router router = Router.router(vertx);

		router.get("/productList").handler(this::getProducts);

		router.route().handler(BodyHandler.create().setUploadsDirectory("uploads").setDeleteUploadedFilesOnEnd(true));

	    // 注册 客户消息解码器
	    eventBus.registerDefaultCodec(Product.class, new ProductCodec());
	    
		HttpServer server = vertx.createHttpServer();
		server.requestHandler(router::accept).listen(8089);
		/*server.requestHandler(req -> {
			if (req.method() == HttpMethod.GET) {
				req.response().setChunked(true);

				if (req.path().equals("/products")) {
					vertx.eventBus().<String>send(SpringDemoVerticle.ALL_PRODUCTS_ADDRESS, "", result -> {
						if (result.succeeded()) {
							req.response().setStatusCode(200).write(result.result().body()).end();
						} else {
							req.response().setStatusCode(500).write(result.cause().toString()).end();
						}
					});
				} else if (req.path().equals("/addProduct")) {
					String desc = req.getParam("desc");
					Product p = new Product();
					p.setDescription("serverGen");
					p.setCreateTime(new Date());
					vertx.eventBus().<String>send(SpringDemoVerticle.ADD_PRODUCT, p, result -> {
						if (result.succeeded()) {
							req.response().setStatusCode(200).write(result.result().body()).end();
						} else {
							req.response().setStatusCode(500).write(result.cause().toString()).end();
						}
					});
				} else {
					req.response().setStatusCode(200).write("Hello from vert.x").end();
				}

			} else {
				// We only support GET for now
				req.response().setStatusCode(405).end();
			}
		});*/
	}


	private void getProducts(RoutingContext context) {
		logger.info("thread {} in event-loop in",Thread.currentThread().getName());
		exeInBlocking(future-> {
					try {
						logger.info("thread {} in workThread",Thread.currentThread().getName());
						logger.info("getall products action");
						List<Product> list = service.getAllProducts();
						future.complete(ResultGenerator.genSuccessResult(list));
					} catch (Exception e) {
						logger.error("work线程执行错误 {}",e);
						future.fail(e);
					}
				}
				, context);
	}

	/**
	 * 封装公共方法到方法中
	 *
	 * @param blockingCodeHandler
	 * @param context
	 */
	private void exeInBlocking(Handler<Future<Result>> blockingCodeHandler, RoutingContext context, SerializerFeature... serializerFeature){
		vertx.executeBlocking(blockingCodeHandler,false,
				result -> {
					logger.info("thread {} in event-loop out",Thread.currentThread().getName());
					if (result.succeeded()) {
						Result result1 = result.result();
						outPutJson(context, result1,serializerFeature);
					} else {
						Result result1 = ResultGenerator.genFailResult(result.cause().getMessage());
						outPutJson(context, result1,serializerFeature);
					}
				});
	}

	/**
	 * 统一向浏览器端输出字符
	 * @param context
	 * @param result
	 */
	private void outPutJson(RoutingContext context, Result result,SerializerFeature... serializerFeature) {
		if(serializerFeature.length == 0){//什么特性都没有传 用这个默认的配置
			final String encoded = JSON.toJSONString(result, SerializerFeature.BrowserCompatible,SerializerFeature.WriteNonStringValueAsString);
			context.response().putHeader("content-type", "application/json").end(encoded);
		}else{
			final String encoded = JSON.toJSONString(result, serializerFeature);//给刷一刷 获取时间的
			context.response().putHeader("content-type", "application/json").end(encoded);
		}

	}
}
